/******************************************************************
 *
 * Copyright 2014 Samsung Electronics All Rights Reserved.
 *
 *
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 ******************************************************************/

#include <string.h>
#include <math.h>

#include "cacommon.h"
#include "caadapterutils.h"
#include "cafragmentation.h"

/**
 * Debugging tag for fragmentation module.
 */
#define CA_FRAGMENTATION_TAG "CA_FRAGMENTATION"

CAResult_t CAGenerateHeader(uint8_t *header,
                            size_t headerLength,
                            size_t dataLength)
{
    OIC_LOG(DEBUG, CA_FRAGMENTATION_TAG, "IN");

    VERIFY_NON_NULL(header, CA_FRAGMENTATION_TAG, "header is NULL");

    if (headerLength < CA_HEADER_LENGTH)
    {
        return CA_STATUS_FAILED;
    }

    if (dataLength > MAX_DATA_LENGTH_SUPPORTED)
    {
        OIC_LOG_V(WARNING,
                  CA_FRAGMENTATION_TAG,
                  "Given length is more than %d.  It will be truncated.",
                  MAX_DATA_LENGTH_SUPPORTED);
    }

    // Only bother initializing the header section of the buffer.  It
    // is up to the caller to handle the data section.
    memset(header, 0, CA_HEADER_LENGTH);

    // If length is more than 4095 then it will be truncated.
    header[1] = dataLength & 0xFF;
    dataLength >>= 8;
    header[0] = dataLength & 0x0F;
    header[0] = header[0] | 0x40; // Adding version 0100.
                                  // (Not used. Future use)

    OIC_LOG(DEBUG, CA_FRAGMENTATION_TAG, "OUT");

    return CA_STATUS_OK;
}

uint32_t CAParseHeader(const uint8_t *header, size_t length)
{
    OIC_LOG(DEBUG, CA_FRAGMENTATION_TAG, "IN");

    VERIFY_NON_NULL_RET(header, CA_FRAGMENTATION_TAG, "header is NULL", 0);

    uint32_t dataLen = 0;

    if (length >= CA_HEADER_LENGTH)
    {
        dataLen = ((header[0] & 0x0F) << 8) | (header[1] & 0xFF);
    }

    OIC_LOG(DEBUG, CA_FRAGMENTATION_TAG, "OUT");

    return dataLen;
}
